package com.vcourse.cloud.oss.controller;

import com.aliyun.oss.OSS;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.vcourse.commons.result.R;
import com.vcourse.commons.result.ResultCodeEnum;
import com.vcourse.service.base.exception.CustomException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Zengsh123
 * @date 2020-05-29 14:53
 * 服务端签名返回前端，前端直传
 */
@Api("阿里云OSS服务")
@Slf4j
@RestController
@RequestMapping("cloud/oss")
public class OssController {
    @Resource
    private OSS client;
    @Value("${spring.cloud.alicloud.oss.endpoint}")
    private String endPoint;
    @Value("${spring.cloud.alicloud.access-key}")
    private String accessId;
    @Value("${oss.bucketname}")
    private String bucketName;

    @ApiOperation("上传文件请求签名接口")
    @GetMapping("/policy/{dir}")
    public R policy(@ApiParam("文件目录") @PathVariable String dir){
        String host = "https://" + bucketName + "." + endPoint;
        // 按日期时间整理文件夹： Avatar/2020/5/29
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
        String format = LocalDate.now().format(dateFormatter);
        dir += "/" +  format;
        Map<String, String> respMap = new LinkedHashMap<String, String>();
        try {
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = client.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = client.calculatePostSignature(postPolicy);

            respMap.put("accessid", accessId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));

            return R.ok().data(respMap).message("文件上传成功");
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new CustomException(ResultCodeEnum.FILE_UPLOAD_ERROR);
        }
    }

    @ApiOperation("删除文件")
    @DeleteMapping("/deleteFiles")
    public R deleteFiles(@ApiParam("OSS文件包含文件后缀在内的完整路径") @RequestBody List<String> files) {
        DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucketName);
        // 设置为简单模式
        deleteObjectsRequest.setQuiet(true);
        // 要删除的文件
        deleteObjectsRequest.withKeys(files);
        // 执行删除
        DeleteObjectsResult deleteObjectsResult = client.deleteObjects(deleteObjectsRequest);
        // 删除结果。详细模式下为删除成功的文件列表(默认)，简单模式下为删除失败的文件列表。
        List<String> deletedFailObjects = deleteObjectsResult.getDeletedObjects();
        if (deletedFailObjects.size() > 0) {
            return R.setResult(ResultCodeEnum.FILE_DELETE_ERROR).data(deletedFailObjects);
        }
        return R.ok().message("删除文件成功");
    }
}
